数据手册:
门主引擎ESP-IDF入门至I2C传感器 链接: https://pan.baidu.com/s/1eXT28D1Oc97pWO51TVyMew?pwd=sq63 提取码: sq63


传感器是一种能感知物理世界信息(如温度、湿度、光照等)并将其转换为电信号的器件。
AHT30 是一款温湿度传感器,由 Asair(奥松)生产,能同时测量环境的温度和相对湿度。它通过 I2C 总线与微控制器(如 ESP32-S3)通信,将测量数据传输给主控芯片处理。应用场景包括:智慧家居、智慧农场、智能工厂等环境监测。
AHT30 是一款只支持 I2C 通信接口的温湿度传感器。它没有 SPI 或 UART 接口,因此 ESP32-S3 必须通过 I2C 协议与它通信。
I2C 的优势在于:
ESP32-S3 内置 2 个 I2C 控制器,每个都可配置为主机模式,直接驱动 AHT30。
想象你是一个工厂厂长(ESP32-S3),你需要同时管理多个工人(传感器、OLED 屏幕、EEPROM)。如果每个工人都需要一条专属电话线,你很快就会没有电话线可用。
I2C 的诞生就是为了解决这个问题:用最少的线(只需 2 根),让一个主机同时管理多个从机设备。
具体来说,I2C 解决了以下痛点:
2.1 基本概念
I2C(Inter-Integrated Circuit,集成电路间总线) 是一种串行同步半双工通信协议,由飞利浦(Philips)公司发明,专为芯片间短距离通信设计。
它只需要两根线:
- SDA(Serial Data Line):串行数据线,传输数据
- SCL(Serial Clock Line):串行时钟线,同步时序
- 这两根线都设置为漏极开漏(open-drain)输出,需要通过上拉电阻连接到电源。

2.2 主机与从机
I2C 总线支持多主机、多从机架构:
- 主机(Master):发起通信、产生时钟信号(如 ESP32-S3)
- 从机(Slave):响应主机请求(如 AHT30 传感器)
- 同一时刻只有一个主机能占用总线访问一个从机
每个从机有唯一的地址(7位或10位),主机通过地址找到目标设备。
2.3 通信流程(技术原理)
一次完整的 I2C 通信过程如下:
- 主机发出 START 信号:SCL 为高电平时,拉低 SDA
- 主机发送 9 个时钟脉冲:
- 前 8 个:7位从机地址 + 1位读/写标志
- 第 9 个:从机拉低 SDA 表示 ACK(应答)
- 根据读/写标志,传输数据(每字节后跟一个 ACK 位)
- 主机发出 STOP 信号:SCL 为高电平时,拉高 SDA
- 若需切换读写方向,发送 RESTART 信号
**关键规则:**SDA 线仅在 SCL 为低电平时才能改变数据,SCL 高电平期间数据必须稳定。 [ESP32-S3技术参考]

2.4 I2C 速度模式
⚠️ 注意:ESP-IDF 驱动层建议主机模式 SCL 不超过 400 kHz。 [ESP32-S3 I2C接口]
2.5 上拉电阻的重要性
SCL 频率受上拉电阻和导线电容影响:
- 推荐上拉电阻:1 kΩ ~ 10 kΩ(通常 2 kΩ ~ 5 kΩ)
- 频率越高,上拉电阻应越小(但不能小于 1 kΩ)
- 电阻过大会降低电流、增加时钟切换时间、降低频率
ESP32-S3 同时支持这三种通信协议,以下是基于文档的对比:
简单总结:
- ****
- ****
- ****
ESP32-S3 AHT30
GPIO (SDA) ──────── SDA─────[4.7kΩ]────3.3V(上拉电阻)
GPIO (SCL) ──────── SCL─────[4.7kΩ]────3.3V(上拉电阻)
GND ──────────── GND
3.3V ──────────── VCC
AHT30 的数据读取遵循以下步骤(与同类传感器 SHT40的流程一致):

读取到的 6 字节原始数据需要转换为物理量(以同类传感器为例):
| ((raw[0] * 256.0 + raw[1]) * 175 / 65535.0) - 45 | |
((raw[3] * 256.0 + raw[4]) * 100 / 65535.0) |
七、Why: 为什么必须看懂时序图?(机器之间通信的语言)
ESP-IDF 提供了 I2C 的"通信工具"(i2c_master_transmit、i2c_master_receive 等),但它不知道 AHT30 需要什么命令、什么顺序、读多少字节。这些信息只存在于 AHT30 的数据手册(Datasheet) 里,以时序图的形式呈现。
****
AHT30 属于 Asair 系列传感器,与同类 I2C 温湿度传感器(如 AHT20)的测量流程高度一致。根据知识库中 AHT20/AHT30 的驱动实现,完整流程如下:
阶段一:初始化 I2C 总线与设备
ESP32-S3 (主机) AHT30 (从机, 地址 0x38)
| |
|── 初始化 I2C 总线 ──────|
|── 挂载设备 (0x38) ──────|
| |
阶段二:发送测量触发命令(写操作)
S → [0x38 + W] → ACK → [命令字节1] → ACK → [命令字节2] → ACK → P
用 ESP-IDF 表达:
uint8_t trigger_cmd[] = {0xAC, 0x33, 0x00}; // AHT30 触发测量命令
i2c_master_transmit(dev_handle, trigger_cmd, 3, -1);⚠️ 具体命令字节(0xAC、0x33、0x00)请以 AHT30 官方数据手册为准,知识库中未包含 AHT30 完整寄存器定义。
阶段三:等待测量完成
传感器需要时间完成测量(通常 80ms 左右),在此期间不能读取数据:
vTaskDelay(pdMS_TO_TICKS(80)); // 等待测量完成阶段四:读取原始数据(读操作)
S → [0x38 + R] → ACK → [字节0] → ACK → [字节1] → ACK → ... → [字节5] → NACK → P
用 ESP-IDF 表达:
uint8_t raw_data[6] = {0};
i2c_master_receive(dev_handle, raw_data, 6, -1);
uint32_t humidity_raw, temperature_raw;
float temperature, humidity;
aht20_read_temperature_humidity(handle, &humidity_raw, &humidity, &temperature_raw, &temperature);
ESP_LOGI(TAG, "humidity: %.2f %%", humidity);
ESP_LOGI(TAG, "temperature: %.2f degC", temperature);
第一步:找到"写操作"和"读操作"的边界
时序图中,每次出现 S(START) 就是一次新的操作开始,出现 P(STOP) 就是结束。
- 如果地址后面是 W(写):主机在发数据给传感器(命令)
- 如果地址后面是 R(读):主机在从传感器读数据
第二步:数清楚字节数
时序图中每个方框代表一个字节(8位)。数清楚:
- 写了几个字节?→ 决定 transmit 的 buffer 大小
- 读了几个字节?→ 决定 receive 的 buffer 大小
第三步:注意 RESTART(Sr)
有些传感器的"写命令 + 读数据"是一次不间断的事务(中间用 Sr 而不是 P+S)。
这种情况用 i2c_master_transmit_receive 一次完成:
uint8_t cmd[2] = {0xAC, 0x33};
uint8_t data[6] = {0};
// 先写命令,再读数据,中间用 RESTART 连接
i2c_master_transmit_receive(dev_handle, cmd, 2, data, 6, -1);
时序图中如果标注了 "Wait" 或 "tMEAS"(测量时间),说明发完命令后需要 vTaskDelay 等待,不能立即读取。
程序通过向从机发送寄存器地址实现读写操作控制,读取时采用写寄存器地址以及读数据事务,写入时采用写寄存器地址以及写数据事务,对应时序图如图I2C时序图,根据时序图,程序执行可总结为以下阶段:

- 起始条件:时序图中表示为 S,主机发送起始条件,标志一次 I2C 事务开始,SDA 由高拉低,SCL 保持高电平。
- 主机地址写入:时序图中表示为 AW : D0 W,主机在 SCL 的上升沿向从机发送 7 位从机地址加 1 位写标志(W),SDA 输出地址和写标志,每一位数据在 SCL 高电平时被从机采样。
- 从机应答:时序图中表示为 A,从机接收到地址并识别为写操作后,拉低** SDA 发送 ACK**。
- 主机数据写入:时序图中表示为 Data write: 75,主机向从机发送寄存器数据,SDA 输出数据,每一位数据对应 SCL 的高电平进行采样。
- 从机应答:时序图中表示为 A,从机接收到数据后拉低 SDA 发送 ACK。
- 重复起始条件:时序图中表示为** Sr**,主机发送重复起始条件,准备进行读取操作,SDA 由高拉低,SCL 保持高电平。
- 主机地址读取:时序图中表示为 AR : D1 R,主机在 SCL 的上升沿向从机发送 7 位从机地址加 1 位读标志(R),SDA 输出地址和读标志,每一位数据在 SCL 高电平时被从机采样。
- 从机数据读取:时序图中表示为 Read write: 68,从机将寄存器数据输出到 SDA,主机在 SCL 上升沿采样数据。
- 主机应答:时序图中表示为 N,主机接收最后一字节后拉高 SDA 发送 NACK,表示本次读操作结束。
- 停止条件:时序图中表示为** P**,主机发送停止条件,结束本次 I2C 事务,SDA 由低拉高,SCL 保持高电平。

I2C 主机写入
在成功安装 I2C 主机总线之后,可以通过调用 i2c_master_transmit() 来向从机设备写入数据。下图解释了该函数的原理。
简单来说,驱动程序用一系列命令填充了一个命令链,并将该命令链传递给 I2C 控制器执行。
I2C 主机读取
在成功安装 I2C 主机总线后,可以通过调用 i2c_master_receive() 从从机设备读取数据。下图解释了该函数的原理。
